package com.panopset.sf;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.HierarchyBoundsAdapter;
import java.awt.event.HierarchyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;

import com.panopset.compat.Zombie;

/**
 * Resizable Osgw panel.
 * 
 * @author Karl Dinwiddie
 * 
 */
public abstract class OsgwResizable {

	private int refreshRate = Osgw.DEFAULT_SLEEP_CYCLE;

	/**
	 * 300 test size.
	 */
	private static final int TS = 300;

	public OsgwResizable(int sleepCycle) {
		refreshRate = sleepCycle;
		getPanel().addHierarchyBoundsListener(new HierarchyBoundsAdapter() {
			@Override
			public void ancestorResized(final HierarchyEvent e) {
				update();
			}
		});
		update();
	}

	public OsgwResizable() {
		this(Osgw.DEFAULT_SLEEP_CYCLE);
	}

	/**
	 * 
	 * @param s
	 *            Not used.
	 */
	public static void main(final String... s) {
		JFrame f = new JFrame();
		f.setLocation(TS, TS);
		f.setSize(TS, TS);
		f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		f.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosed(final WindowEvent e) {
				Zombie.stop();
			}
		});
		f.setTitle("OsgwResizable test");
		f.add(new OsgwResizable() {

			@Override
			public void paintCycle(final Graphics2D g) {
				g.setColor(Color.RED);
				g.fillRect(0, 0, getPanel().getWidth(), getPanel().getHeight());
				g.setColor(Color.YELLOW);
				g.fillOval(0, 0, getPanel().getWidth(), getPanel().getHeight());
			}
		}

		.getPanel());
		f.setVisible(true);
	}

	/**
	 * Off screen graphics world.
	 */
	private Osgw osgw;

	/**
	 * 
	 * @return Off screen graphics world.
	 */
	public final Osgw getOsgw() {
		if (osgw == null) {
			osgw = new Osgw(getPanel().getSize().width,
					getPanel().getSize().height, refreshRate) {

				@Override
				public void paintCycle(final Graphics2D g) {
					OsgwResizable.this.paintCycle(g);
				}

			};
		}
		return osgw;
	}

	/**
	 * 
	 * @param g
	 *            Graphics2D.
	 */
	public abstract void paintCycle(Graphics2D g);

	/**
	 * Bound parent size.
	 */
	private Dimension boundParentSize;

	/**
	 * Update.
	 */
	private void update() {
		if (panel == null) {
			return;
		}
		if (panel.getSize().height == 0) {
			return;
		}
		if (panel.getSize().width == 0) {
			return;
		}
		if (boundParentSize != null
				&& getPanel().getSize().equals(boundParentSize)) {
			return;
		}
		panel.removeAll();
		osgw = null;
		panel.add(getOsgw().getPanel());
		boundParentSize = getPanel().getSize();
		getPanel().invalidate();
		getPanel().getTopLevelAncestor().validate();
	}

	/**
	 * Panel.
	 */
	private JPanel panel;

	/**
	 * @return Panel that contains the Osgw.
	 */
	public final JPanel getPanel() {
		if (panel == null) {
			panel = new JPanel(new GridLayout(1, 1));
		}
		return panel;
	}
}
